Python基础之正确重载运算符

您所在的位置:网站首页 python 基本运算符 Python基础之正确重载运算符

Python基础之正确重载运算符

#Python基础之正确重载运算符| 来源: 网络整理| 查看: 265

导语:本文章记录了本人在学习Python基础之面向对象篇的重点知识及个人心得,打算入门Python的朋友们可以来一起学习并交流。

本文重点:

1、掌握运算符重载的定义和作用,以及Python对其的内部限制;2、掌握一元运算符重载设计思路;3、理解中缀运算符重载过程中鸭子类型和白鹅类型思想的运用并掌握。 一、运算符重载基础

运算符重载:对已有的运算符进行重新定义,赋予其另一种功能,以适应不同的数据类型。重载的作用:令用户定义的对象能够使用中缀运算符(如 + 和 | )或一元运算符(如 - 和 ~ )等运算符。为了做好灵活性、可用性和安全性方面的平衡,Python对运算符重载施加了一些限制:

不能重载内置类型的运算符; 能新建运算符,只能重载现有运算符; 某些运算符不能重载,如is、and、or和not(不过位运算符&、| 和 ~可以)。 二、一元运算符 1、常见的一元运算符 -(__neg__),一元取负算术运算符。例:若 x 是 -2,则 -x==2。 +(__pos__),一元取正算术运算符。通常x==+x。 ~(__invert__),对整数按位取反,~x== -(x+1)。例:若 x 是 -2,则 ~x==1。

另外,Python语言参考手册将内置的abs()函数列为一元运算符,它对应的特殊方法是__abs__。

2、重载一元运算符

重载一元运算符只需实现相应的特殊方法,这些特殊方法只有self一个参数。重载应遵循运算符的一个基本规则:始终返回一个新对象。即,不能修改self,要创建并返回合适类型的新实例。

下面我们以第10章的多维向量类为例重载一元运算符:

import math class Vector: #排版需要省略中间代码 def __abs__(self): return math.sqrt(sum(x*x for x in self)) def __neg__(self): return Vector(-x for x in self) def __pos__(self): return Vector(self) def __invert__(self): return Vector(-x-1 for x in self) 3、x和+x不相等的情况 算术运算上下文的精度变化可能导致 x 不等于 +x

图片描述Python 3.4 为 Decimal 算术运算设定的默认精度是28,这里因为+x使用上下文的精度导致相等性判断返回False。

counter实例不含零值和负值计算器

图片描述通过上面的实例能够看到counter实例ct经过零值和负值的赋值之后,再经过+x运算后发现ct实例中的非负数对象均消失了。事实上一元运算符 + 等同于加上一个空 Counter。当Counter相加时,Python解释器从实用性角度出发会把负值和零值的计数从结果中剔除。

三、中缀运算符 1、重载加法__add__

现在我们仍以第10章的多维向量为例进行中缀运算符加号“+”的重载。重载加法的目标分析:

当多维向量类是操作数时,多维向量应支持与同类向量的加法; 同时多维向量类还应支持与可迭代对象的加法; 此外当可迭代对象是操作数的时候,多维对象应具备__radd__如此来调用多维向量类中的__add__方法。

重载加法的流程图设计:设计的重点在于采用鸭子类型思想。当多维向量类与非数值类相加时,多维向量类无法处理异类加法运算可以将加法运算交给右操作数的类处理。因为右操作数存在可以处理这种异类加法的可能。图片描述

重载加法的代码实现:

from itertools import zip_longest class Vector: #排版需要省略中间代码 def __add__(self, other): try: return Vector(a+b for a,b in zip_longest(self,other,fillvalue=0)) except TypeError: return NotImplemented def __radd__(self, other): return self+other

2、重载乘法__mul__重载加法的目标分析:

当多维向量类是操作数时,多维向量应支持与同类向量的乘法; 同时多维向量类还应支持与可迭代对象的加法; 此外当可迭代对象是操作数的时候,多维对象应具备__rmul__如此来调用多维向量类中的__mul__方法。

注意:我们对多维向量重载的乘法是针对数论中的实数类型进行运算,此时可以采用白鹅类型显式检查对象的抽象基类是否为numbers.Real,代码实现如下:

import numbers class Vector: #排版需要省略中间代码 def __mul__(self, other): if isinstance(other,numbers.Real): return Vector(x*other for x in self) else: return NotImplemented def __rmul__(self, other): return self*other

Tips:一般来说只有当处理与self不同类型的操作数时,需要创建反向方法处理。否则没有必要创建反向方法。

四、比较运算符

Python 解释器对众多比较运算符(==、 !=、 >、 =、



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3